#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <DNSServer.h>
#include <WiFiManager.h> // https://github.com/tzapu/WiFiManager
#include <PubSubClient.h>
#include <ArduinoJson.h>

// 配置存储 - 使用EEPROM保存设置
#include <EEPROM.h>

// 配置结构体
struct Config {
  char ssid[32];
  char password[64];
  char mqtt_server[40];
  int mqtt_port;
  char mqtt_topic[64];
  char clientId[32];
  char command[64];
  bool configReady;
};

Config config;
const int configVersion = 1; // 用于配置版本控制

// Web服务器
ESP8266WebServer server(80);
WiFiClient espClient;
PubSubClient mqttClient(espClient);

// 初始化EEPROM
void initEEPROM() {
  EEPROM.begin(512);
  // 读取配置
  EEPROM.get(0, config);
  
  // 检查配置是否有效
  if (config.configReady != configVersion) {
    // 配置无效或未初始化，设置默认值
    strcpy(config.ssid, "hgsy");
    strcpy(config.password, "hg111111");
    strcpy(config.mqtt_server, "192.168.1.222");
    config.mqtt_port = 1883;
    strcpy(config.mqtt_topic, "bms48200/data");
    strcpy(config.clientId, "ESP8266_BMS_Client-gs");
    strcpy(config.command, "~200046F2E00201FD24\r");
    config.configReady = configVersion;
    
    // 保存默认配置
    saveConfig();
  }
}

// 保存配置到EEPROM
void saveConfig() {
  EEPROM.put(0, config);
  EEPROM.commit();
  Serial.println("Config saved");
}

// 连接WiFi
void connectWiFi() {
  WiFi.mode(WIFI_STA);
  WiFi.begin(config.ssid, config.password);
  
  Serial.print("Connecting to ");
  Serial.println(config.ssid);
  
  int attempts = 0;
  while (WiFi.status() != WL_CONNECTED && attempts < 20) {
    delay(500);
    Serial.print(".");
    attempts++;
  }
  
  if (WiFi.status() != WL_CONNECTED) {
    Serial.println("WiFi connection failed. Starting AP for configuration");
    startAP();
  } else {
    Serial.println();
    Serial.println("WiFi connected");
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
    
    // 设置mDNS，以便通过http://esp8266.local访问
    if (MDNS.begin("esp8266")) {
      Serial.println("mDNS responder started");
    }
  }
}

// 启动AP模式进行配置
void startAP() {
  WiFi.mode(WIFI_AP);
  WiFi.softAP("ESP8266 Config", "password");
  
  Serial.println("AP started");
  Serial.print("IP address: ");
  Serial.println(WiFi.softAPIP());
  
  // 设置mDNS
  if (MDNS.begin("esp8266")) {
    Serial.println("mDNS responder started");
  }
  
  // 设置Web服务器路由
  setupServerRoutes();
  
  // 启动服务器
  server.begin();
  Serial.println("Web server started");
}

// 连接MQTT
void connectMQTT() {
  mqttClient.setServer(config.mqtt_server, config.mqtt_port);
  
  while (!mqttClient.connected()) {
    Serial.print("Attempting MQTT connection...");
    
    if (mqttClient.connect(config.clientId)) {
      Serial.println("connected");
      // 订阅响应主题（如果有）
      // mqttClient.subscribe("bms48200/response");
    } else {
      Serial.print("failed, rc=");
      Serial.print(mqttClient.state());
      Serial.println(" try again in 5 seconds");
      delay(5000);
    }
  }
}

// 发送命令到MQTT
void sendCommand() {
  if (mqttClient.connected()) {
    mqttClient.publish(config.mqtt_topic, config.command);
    Serial.print("Sent command: ");
    Serial.println(config.command);
  }
}

// 设置Web服务器路由
void setupServerRoutes() {
  // 根路径 - 返回配置页面
  server.on("/", []() {
    String page = "<html><body>";
    page += "<h1>ESP8266 Configuration</h1>";
    page += "<form action=\"/save\" method=\"post\">";
    
    page += "<h2>WiFi Configuration</h2>";
    page += "SSID: <input type=\"text\" name=\"ssid\" value=\"" + String(config.ssid) + "\"><br>";
    page += "Password: <input type=\"password\" name=\"password\" value=\"" + String(config.password) + "\"><br>";
    
    page += "<h2>MQTT Configuration</h2>";
    page += "Server: <input type=\"text\" name=\"mqtt_server\" value=\"" + String(config.mqtt_server) + "\"><br>";
    page += "Port: <input type=\"number\" name=\"mqtt_port\" value=\"" + String(config.mqtt_port) + "\"><br>";
    page += "Topic: <input type=\"text\" name=\"mqtt_topic\" value=\"" + String(config.mqtt_topic) + "\"><br>";
    page += "Client ID: <input type=\"text\" name=\"clientId\" value=\"" + String(config.clientId) + "\"><br>";
    
    page += "<h2>Command</h2>";
    page += "Command: <input type=\"text\" name=\"command\" value=\"" + String(config.command) + "\"><br>";
    
    page += "<input type=\"submit\" value=\"Save Config\">";
    page += "</form>";
    
    page += "<h2>Actions</h2>";
    page += "<a href=\"/send\">Send Command</a><br>";
    page += "<a href=\"/restart\">Restart Device</a><br>";
    
    page += "</body></html>";
    
    server.send(200, "text/html", page);
  });
  
  // 保存配置
  server.on("/save", []() {
    if (server.hasArg("ssid")) strcpy(config.ssid, server.arg("ssid").c_str());
    if (server.hasArg("password")) strcpy(config.password, server.arg("password").c_str());
    if (server.hasArg("mqtt_server")) strcpy(config.mqtt_server, server.arg("mqtt_server").c_str());
    if (server.hasArg("mqtt_port")) config.mqtt_port = server.arg("mqtt_port").toInt();
    if (server.hasArg("mqtt_topic")) strcpy(config.mqtt_topic, server.arg("mqtt_topic").c_str());
    if (server.hasArg("clientId")) strcpy(config.clientId, server.arg("clientId").c_str());
    if (server.hasArg("command")) strcpy(config.command, server.arg("command").c_str());
    
    saveConfig();
    
    server.send(200, "text/plain", "Config saved! Restarting in 5 seconds...");
    
    // 重启设备
    delay(5000);
    ESP.restart();
  });
  
  // 发送命令
  server.on("/send", []() {
    sendCommand();
    server.send(200, "text/plain", "Command sent!");
  });
  
  // 重启设备
  server.on("/restart", []() {
    server.send(200, "text/plain", "Restarting device in 2 seconds...");
    delay(2000);
    ESP.restart();
  });
  
  // 获取当前配置（JSON格式）
  server.on("/config", []() {
    DynamicJsonDocument doc(1024);
    doc["ssid"] = config.ssid;
    doc["password"] = config.password;
    doc["mqtt_server"] = config.mqtt_server;
    doc["mqtt_port"] = config.mqtt_port;
    doc["mqtt_topic"] = config.mqtt_topic;
    doc["clientId"] = config.clientId;
    doc["command"] = config.command;
    
    String json;
    serializeJson(doc, json);
    
    server.send(200, "application/json", json);
  });
}

void setup() {
  Serial.begin(115200);
  Serial.println();
  
  // 初始化EEPROM和配置
  initEEPROM();
  
  // 连接WiFi
  connectWiFi();
  
  // 设置Web服务器路由
  setupServerRoutes();
  
  // 启动服务器
  server.begin();
  Serial.println("Web server started");
}

void loop() {
  // 处理Web服务器请求
  server.handleClient();
  
  // 处理mDNS请求
  MDNS.update();
  
  // 保持MQTT连接
  if (!mqttClient.connected()) {
    connectMQTT();
  }
  
  // 处理MQTT消息（如果有）
  mqttClient.loop();
  
  // 你的主程序逻辑可以在这里继续
  delay(100);
}    